package com.ruibang.glass.equipment.service.impl.device;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruibang.glass.equipment.constant.Constants;
import com.ruibang.glass.equipment.domain.req.device.AreaManagePageReq;
import com.ruibang.glass.equipment.dto.AreaManageDTO;
import com.ruibang.glass.equipment.dto.SelectDTO;
import com.ruibang.glass.equipment.entity.device.AreaManage;
import com.ruibang.glass.equipment.mapper.device.AreaManageMapper;
import com.ruibang.glass.equipment.service.AreaManageService;

import freemarker.template.utility.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
public class AreaManageServiceImpl extends ServiceImpl<AreaManageMapper, AreaManage> implements AreaManageService {

    @Override
    public IPage<AreaManageDTO> queryAreas(AreaManagePageReq area) {
        List<AreaManage> areaManages = baseMapper.selectList();
        if (StringUtils.isEmpty(area.getAreaName())) {
            IPage<AreaManage> areaManageIPage = baseMapper.queryDeviceCarInfo(new Page<>(area.getPageNo(), area.getPageSize()), area);
            List<AreaManage> records = areaManageIPage.getRecords();
            List<String> parentsIdList = new ArrayList<>();
            List<AreaManageDTO> areaManageDTOS = new ArrayList<>();
            for (AreaManage areaManage : records) {
                AreaManageDTO areaManageDTO = new AreaManageDTO();
                areaManageDTO.setId(areaManage.getId());
                areaManageDTO.setAreaName(areaManage.getAreaName());
                areaManageDTO.setParentId(areaManage.getParentId());
                areaManageDTO.setLevel(areaManage.getLevel());
                areaManageDTOS.add(areaManageDTO);
            }
            parentsIdList = records.stream().map(AreaManage::getId).collect(Collectors.toList());
            getAllChidList(areaManageDTOS, areaManages, parentsIdList);
            List<AreaManageDTO> areaManageDTOS1 = cleanSource(areaManageDTOS);
            IPage<AreaManageDTO> areaManageDTOIPage = new Page<>();
            areaManageDTOIPage.setRecords(areaManageDTOS1);
            areaManageDTOIPage.setTotal(areaManageIPage.getTotal());
            areaManageDTOIPage.setPages(areaManageIPage.getPages());
            areaManageDTOIPage.setSize(areaManageIPage.getSize());
            areaManageDTOIPage.setCurrent(areaManageIPage.getCurrent());
            return areaManageDTOIPage;
        }
        List<AreaManage> areaManages1 = baseMapper.searchNameList(area.getAreaName());
        List<String> areaIdList = areaManages1.stream().map(AreaManage::getId).collect(Collectors.toList());
        List<AreaManageDTO> areaManageDTOS = new ArrayList<>();
        getAllParentList(areaManageDTOS, areaManages, areaIdList);
        List<AreaManageDTO> areaManageDTOS1 = cleanSource(areaManageDTOS);
        IPage<AreaManageDTO> areaManageDTOIPage = new Page<>();
        areaManageDTOIPage.setRecords(areaManageDTOS1);
        areaManageDTOIPage.setTotal(areaManageDTOS1.size());
        areaManageDTOIPage.setPages(area.getPageNo());
        areaManageDTOIPage.setSize(area.getPageSize());
        return areaManageDTOIPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<AreaManageDTO> queryAreasList(AreaManagePageReq area) {
        List<AreaManage> areaManages = this.lambdaQuery().eq(AreaManage::getIsDelete, Constants.ZERO_STR).list();
        if (StringUtils.isEmpty(area.getAreaName())) {
            IPage<AreaManage> areaManageIPage = baseMapper.queryDeviceCarInfo(new Page<>(area.getPageNo(), area.getPageSize()), area);
            List<AreaManage> records = areaManageIPage.getRecords();
            List<String> parentsIdList = new ArrayList<>();
            List<AreaManageDTO> areaManageDTOS = new ArrayList<>();
            for (AreaManage areaManage : records) {
                AreaManageDTO areaManageDTO = new AreaManageDTO();
                areaManageDTO.setId(areaManage.getId());
                areaManageDTO.setAreaName(areaManage.getAreaName());
                areaManageDTO.setParentId(areaManage.getParentId());
                areaManageDTO.setLevel(areaManage.getLevel());
                areaManageDTOS.add(areaManageDTO);
            }
            parentsIdList = records.stream().map(AreaManage::getId).collect(Collectors.toList());
            getAllChidList(areaManageDTOS, areaManages, parentsIdList);
            List<AreaManageDTO> areaManageDTOS1 = cleanSource(areaManageDTOS);
            IPage<AreaManageDTO> areaManageDTOIPage = new Page<>();
            areaManageDTOIPage.setRecords(areaManageDTOS1);
            areaManageDTOIPage.setTotal(areaManageIPage.getTotal());
            areaManageDTOIPage.setPages(areaManageIPage.getPages());
            areaManageDTOIPage.setSize(areaManageIPage.getSize());
            areaManageDTOIPage.setCurrent(areaManageIPage.getCurrent());
            return areaManageDTOS1;
        }
        List<AreaManage> areaManages1 = baseMapper.searchNameList(area.getAreaName());
        List<String> parentsIdList = new ArrayList<>();
        List<AreaManageDTO> areaManageDTOS = new ArrayList<>();
        for (AreaManage areaManage : areaManages1) {
            AreaManageDTO areaManageDTO = new AreaManageDTO();
            areaManageDTO.setId(areaManage.getId());
            areaManageDTO.setAreaName(areaManage.getAreaName());
            areaManageDTO.setParentId(areaManage.getParentId());
            areaManageDTO.setLevel(areaManage.getLevel());
            areaManageDTOS.add(areaManageDTO);
        }
        parentsIdList = areaManages1.stream().map(AreaManage::getId).collect(Collectors.toList());
        getAllChidList(areaManageDTOS, areaManages, parentsIdList);
        List<AreaManageDTO> areaManageDTOS1 = cleanSource(areaManageDTOS);
        IPage<AreaManageDTO> areaManageDTOIPage = new Page<>();
        areaManageDTOIPage.setRecords(areaManageDTOS1);
        areaManageDTOIPage.setTotal(areaManages1.size());
        areaManageDTOIPage.setPages(area.getPageNo());
        areaManageDTOIPage.setSize(area.getPageSize());
        return areaManageDTOS1;


//        List<String> areaIdList = areaManages1.stream().map(AreaManage::getId).collect(Collectors.toList());
//        List<AreaManageDTO> areaManageDTOS = new ArrayList<>();
//        getAllParentList(areaManageDTOS, areaManages, areaIdList);
//        List<AreaManageDTO> areaManageDTOS1 = cleanSource(areaManageDTOS);
//        IPage<AreaManageDTO> areaManageDTOIPage = new Page<>();
//        areaManageDTOIPage.setRecords(areaManageDTOS1);
//        areaManageDTOIPage.setTotal(areaManageDTOS1.size());
//        areaManageDTOIPage.setPages(area.getPageNo());
//        areaManageDTOIPage.setSize(area.getPageSize());
//        return areaManageDTOS1;
    }


    //父层级获取所有子层级
    public void getAllChidList(List<AreaManageDTO> areaManageDTOS, List<AreaManage> allAreaManages, List<String> parentsIdList) {
        List<AreaManageDTO> newList = new ArrayList<>();
        for (AreaManage areaManage : allAreaManages) {
            for (String id : parentsIdList) {
                if (areaManage.getParentId().equals(id)) {
                    AreaManageDTO areaManageDTO = new AreaManageDTO();
                    areaManageDTO.setId(areaManage.getId());
                    areaManageDTO.setAreaName(areaManage.getAreaName());
                    areaManageDTO.setParentId(areaManage.getParentId());
                    areaManageDTO.setLevel(areaManage.getLevel());
                    newList.add(areaManageDTO);
                }
            }
        }
        if (CollectionUtils.isEmpty(newList)) {
            return;
        }
        areaManageDTOS.addAll(newList);
        List<String> collect = newList.stream().map(AreaManageDTO::getId).collect(Collectors.toList());
        getAllChidList(areaManageDTOS, allAreaManages, collect);
    }

    // 数据组装
    private List<AreaManageDTO> cleanSource(List<AreaManageDTO> areaManageDTOS) {
        Map<Integer, List<AreaManageDTO>> areaMap = areaManageDTOS.stream().sorted(Comparator.comparing(AreaManageDTO::getLevel)).collect(Collectors.groupingBy(AreaManageDTO::getLevel));
        List<Integer> levelList = areaManageDTOS.stream().sorted(Comparator.comparing(AreaManageDTO::getLevel).reversed()).map(AreaManageDTO::getLevel).distinct().collect(Collectors.toList());
        List<AreaManageDTO> levelAllList = new ArrayList<>();
        for (Integer level : levelList) {
            List<AreaManageDTO> levelOneList = areaMap.get(level);
            if (CollectionUtil.isEmpty(levelAllList)) {
                levelAllList.addAll(levelOneList);
            } else {
                for (AreaManageDTO areaManageDTO : levelOneList) {
                    for (AreaManageDTO manageDTO : levelAllList) {
                        if (areaManageDTO.getId().equals(manageDTO.getParentId())) {
                            if (CollectionUtils.isEmpty(areaManageDTO.getChildren())) {
                                List<AreaManageDTO> addChidren = new ArrayList<>();
                                addChidren.add(manageDTO);
                                areaManageDTO.setChildren(addChidren);
                            } else {
                                List<AreaManageDTO> addChidren = areaManageDTO.getChildren();
                                addChidren.add(manageDTO);
                                areaManageDTO.setChildren(addChidren);
                            }
                        }
                    }
                }
                levelAllList = new ArrayList<>();
                levelAllList.addAll(levelOneList);
            }
        }
        return levelAllList;
    }


    //获取父层级

    public void getAllParentList(List<AreaManageDTO> areaManageDTOS, List<AreaManage> allAreaManages, List<String> idList) {
        List<String> nextId = new ArrayList<>();
        for (AreaManage areaManage : allAreaManages) {
            for (String id : idList) {
                if (id.equals(areaManage.getId()) && areaManage.getLevel().toString().equals("1")) {
                    AreaManageDTO areaManageDTO = new AreaManageDTO();
                    areaManageDTO.setId(areaManage.getId());
                    areaManageDTO.setAreaName(areaManage.getAreaName());
                    areaManageDTO.setParentId(areaManage.getParentId());
                    areaManageDTO.setLevel(areaManage.getLevel());
                    areaManageDTOS.add(areaManageDTO);
                }
                if (id.equals(areaManage.getId()) && !areaManage.getLevel().toString().equals("1")) {
                    AreaManageDTO areaManageDTO = new AreaManageDTO();
                    areaManageDTO.setId(areaManage.getId());
                    areaManageDTO.setAreaName(areaManage.getAreaName());
                    areaManageDTO.setParentId(areaManage.getParentId());
                    areaManageDTO.setLevel(areaManage.getLevel());
                    areaManageDTOS.add(areaManageDTO);
                    nextId.add(areaManage.getId());
                }
            }
            if (CollectionUtils.isEmpty(nextId)) {
                return;
            } else {
                getAllParentList(areaManageDTOS, allAreaManages, nextId);
            }
        }

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addChild(AreaManage areaManage) {
        if (StringUtils.isEmpty(areaManage.getParentId()) || "0".equals(areaManage.getParentId())) {
            areaManage.setParentId("0");
            if (areaManage.getLevel() == null) {
                areaManage.setLevel(1);
            }
            return baseMapper.insert(areaManage);
        }
        int level = areaManage.getLevel() + 1;
        areaManage.setLevel(level);
        return baseMapper.insert(areaManage);
    }

    @Override
    public List<SelectDTO> getAreaNameList() {
        return baseMapper.getAreaNameList();
    }

}
